// relate.cpp
// Customizer_Base
// Protea Customizer/Customizer Pro / Business Logic for managing database relations (keys)
// Copyright (C) 2003, 2004, 2005 eXegeSys, Inc.
// Copyright (C) 2008 Bruce A. James
//
// This program is part of the Protea Project.
//
// The Protea Project is free software; you can redistribute it and/or modify it 
// under the terms of the GNU General Public License as published by the 
// Free Software Foundation, either version 3 of the License, or (at your 
// option) any later version.
//
// The Protea Project is distributed in the hope that it will be useful, but 
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
// for more details.
// 
// You should have received a copy of the GNU General Public License along 
// with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// Please send correspondence to:
//
// theproteaproject@gmail.com
//

#include "base_setup.h"

// DB_RELATE Subtransactions
//
//////////////////////////////////////////////////////////////////////////////

//@ SEC 3
//@ CHA DB Relate Add
//@ COD DBRelateAdd
//@ TAB DBRelate
//@ GEN Use DB Relate Add to add Database Relation records to DBRelate
void DBRelateAdd( XCBuffer* buf, XCTransactionVars* vars )
{
	TRANS_INFUNC( DBRelateAdd );

	//@ Add the DB Relate record
	XCSQLGen* query = vars->query;
	query->MakeFull( SQL_STMT_INSERT, buf );
	vars->dbtxn->ExecuteSQL( query, SQL_NO_RESULT );

	TRANS_OUTFUNC();
};

//@ SEC 3
//@ CHA DB Relate Delete
//@ COD DBRelateDelete
//@ TAB DBRelate
//@ GEN Use DB Relate Delete to delete Database Relation records from DBRelate
void DBRelateDelete( XCBuffer* buf, XCTransactionVars* vars )
{
	TRANS_INFUNC( DBRelateDelete );

	//@ Delete the DB Relate record
	XCSQLGen* query = vars->query;
	query->MakeFull( SQL_STMT_DELETE, buf );
	vars->dbtxn->ExecuteSQL( query, SQL_NO_RESULT );

	TRANS_OUTFUNC();
};

//@ SEC 3
//@ CHA DB Relate Retrieve
//@ COD DBRelateRetrieve
//@ TAB DBRelate
//@ GEN Use DB Relate Retrieve to retrieve Database Relation records from DBRelate
bool DBRelateRetrieve( XCBuffer* buf, XCTransactionVars* vars )
{
	TRANS_INFUNC( DBRelateRetrieve );

	bool result;
	XCDBStatement* stmt = NULL;
	XCSQLGen* query = vars->query;

	try {
		query->MakeFull( SQL_STMT_SELECT, buf );
		stmt = vars->dbtxn->ExecuteSQL( query );
		result = (!stmt->Eof());
	} catch( ... ) {
		App->CleanupObjects( 1, &stmt );
		throw;
	};
	App->CleanupObjects( 1, &stmt );

	TRANS_OUTFUNCRET( result );
};

//@ SEC 3
//@ CHA DB Relate Verify
//@ COD DBRelateVerify
//@ TAB DBRelate
//@ GEN Use DB Relate Verify to verify Database Relation records for processing on DBRelate
void DBRelateVerify( XCBuffer* buf, XCTransactionVars* vars, verify_type verify_mode )
{
	XCBuffer* temp = NULL;
	XCField* fld = NULL;
	XCDBStatement* stmt = NULL;
	XCSQLGen* query = vars->query;

	TRANS_INFUNC( DBRelateVerify );

	//@ UTL LookupNumberFromName to verify that we do have a field with this name.  If it fails,
	//@ ERR E (DOESNT_EXIST) Field doesn't exist
	if ( ! LookupNumberFromName( vars, vars->buffer, buf, FLD_FIELD_NUMBER, FLD_FIELD_NAME, FMT_FIELD_DESCRIPTOR ) )
		vars->Errors->Add( ERR_DOESNT_EXIST, SEV_ERROR, FLD_FIELD_NAME, 1, ERR_FIELD );

	//@ SUB FormatDescRetrieve to verify that we do have a format with this name.  If it fails,
	//@ ERR E (DOESNT_EXIST) Format doesn't exist
	if ( ! LookupNumberFromName( vars, vars->buffer, buf, FLD_FORMAT_NUMBER, FLD_FORMAT_NAME, FMT_FORMAT_DESCRIPTR ) )
		vars->Errors->Add( ERR_DOESNT_EXIST, SEV_ERROR, FLD_FORMAT_NAME, 1, ERR_FORMAT );

	//@ Check for Errors
	vars->Errors->Check();

	//@ If verifying an ADD transaction,
	if (verify_mode == VERIFY_ADD) {
		//@ GRS

			//@ SUB DBRelateRetrieve to verify that the current relation doesn't exist.  If it fails,
			//@ ERR C (ALREADY_EXISTS) DB Relation already exists.
			if ( DBRelateRetrieve( buf, vars ) )
				vars->Errors->Add( ERR_ALREADY_EXISTS, SEV_CRITICAL, 0, 1, ERR_DB_RELATION );

			//@ Ensure that there is only one AutoNumber field per table.
			fld = buf->GetField( FLD_RELATE_TYPE );
			if ( fld->GetLong( true ) == dbr_autonumber )
			{
				temp = App->CreateBuffer( FMT_DB_RELATE, false );
				temp->GetField( FLD_RELATE_TYPE )->MoveField( fld );

				XCCompare comp[ 3 ];
				comp[ 0 ].format = FMT_DB_RELATE;
				comp[ 1 ].format = FMT_DB_RELATE;
				comp[ 2 ].format = FMT_DB_RELATE;
				XCField* where[ 4 ];
				where[ 0 ] = temp->GetField( FLD_APPL_NBR );
				where[ 1 ] = temp->GetField( FLD_FORMAT_NUMBER );
				where[ 2 ] = temp->GetField( FLD_RELATE_TYPE );
				where[ 3 ] = NULL;

				query->MakeSELECT( temp );
				query->AddWHERE( where, comp );

				stmt = vars->dbtxn->ExecuteSQL( query );
				//@ If an AutoNumber field already exists on the table, 
				//@ ERR E (AUTONUMBER_EXISTS) AutoNumber Relation already exists on this Table.
				if (!stmt->Eof())
					vars->Errors->Add( ERR_AUTONUMBER_EXISTS, SEV_ERROR, FLD_FORMAT_NUMBER );
				
				App->CleanupObjects( 2, &stmt, &temp );
			};

		//@ GRE
	} else {
		//@ GRS
		
			//@ SUB DBRelateRetrieve to verify that the current relation does exist.  If it fails,
			//@ ERR C (DOESNT_EXIST) DB Relation doesn't exist.
			if ( !DBRelateRetrieve( buf, vars ) )
				vars->Errors->Add( ERR_DOESNT_EXIST, SEV_CRITICAL, 0, 1, ERR_DB_RELATION );

		//@ GRE
	};
	TRANS_OUTFUNC();
};


//@ SEC 3
//@ CHA DBRelateReviewFormat
//@ COD DBRelateReviewFormat
//@ TAB FieldDescriptor Write
//@ GEN Use FieldRelateFind to locate field relation records for a particular field

XCDBStatement* DBRelateReviewFormat( XCBuffer* input, XCTransactionVars* vars ) {
	XCSQLGen* query = vars->query;
	XCCompare comp[3];
	XCField* fields[4];

	fields[0] = input->GetField( FLD_APPL_NBR );
	fields[1] = input->GetField( FLD_FORMAT_NUMBER );
	fields[2] = NULL;

	query->MakeSELECT( input );
	query->AddWHERE( fields, comp );

	return vars->dbtxn->ExecuteSQL( query );
};





//@ SEC 3
//@ CHA Dataset Descr Retrieve
//@ COD DatasetDescrRetrieve
//@ TAB DATASET_DESCR
//@ GEN Use DatasetDescrRetrieve to add Database Relation records to DBRelate
bool DatasetDescrRetrieve( XCBuffer* buf, XCTransactionVars* vars ) {

	TRANS_INFUNC( DatasetDescrRetrieve );

	bool result;
	XCDBStatement* stmt = NULL;
	XCSQLGen* query = vars->query;

	try {
		query->MakeFull( SQL_STMT_SELECT, buf );
		stmt = vars->dbtxn->ExecuteSQL( query );
		result = (!stmt->Eof());
	} catch( ... ) {
		App->CleanupObjects( 1, &stmt );
		throw;
	};
	App->CleanupObjects( 1, &stmt );

	TRANS_OUTFUNCRET( result );
};





//@ SEC 3
//@ CHA Dataset Descr Add
//@ COD DatasetDescrAdd
//@ TAB DATASET_DESCR
//@ GEN Use Dataset Descr Add to add Database Relation records to DBRelate
void DatasetDescrAdd( XCBuffer* buf, XCTransactionVars* vars ) {

	TRANS_INFUNC( DatasetDescrAdd );

	buf->GetField( FLD_VIEW_FLAG )->SetLong( -1 );

	//@ Add the DB Relate record
	XCSQLGen* query = vars->query;
	query->MakeFull( SQL_STMT_INSERT, buf );
	vars->dbtxn->ExecuteSQL( query, SQL_NO_RESULT );

	TRANS_OUTFUNC();
};







//@ SEC 3
//@ CHA Dataset Descr Delete
//@ COD DatasetDescrDelete
//@ TAB DBRelate
//@ GEN Use DB Relate Delete to delete Database Relation records from DBRelate
void DatasetDescrDelete( XCBuffer* buf, XCTransactionVars* vars )
{
	TRANS_INFUNC( DatasetDescrDelete );

	//@ Delete the DB Relate record
	XCSQLGen* query = vars->query;
	query->MakeFull( SQL_STMT_DELETE, buf );
	vars->dbtxn->ExecuteSQL( query, SQL_NO_RESULT );

	TRANS_OUTFUNC();
};



//@ SEC 3
//@ CHA Dataset Descr Change
//@ COD DatasetDescrChange
//@ TAB DATASET_DESCR
//@ GEN Use DB Relate Delete to delete Database Relation records from DBRelate
void DatasetDescrChange( XCBuffer* buf, XCTransactionVars* vars )
{
	TRANS_INFUNC( DatasetDescrChange );

	//@ Delete the DB Relate record
	XCSQLGen* query = vars->query;
	query->MakeFull( SQL_STMT_UPDATE, buf );
	vars->dbtxn->ExecuteSQL( query, SQL_NO_RESULT );

	TRANS_OUTFUNC();
};
